<template>
  <div class="w-full">
    <!--    <div class="flex mb-2">-->
    <!--      <el-button type="primary" size="small" @click="handleAdd">添加</el-button>-->
    <!--    </div>-->
    <el-table :data="tableData" border stripe>
      <el-table-column label="数据权限" align="center">
        <template #default="{ row }">
          <el-cascader
            v-model="row.dataIdArray"
            :options="cascaderOptions"
            :props="cascaderProps"
            :show-all-levels="false"
            clearable
            @change="handleChangeCascader(row)"
          />
        </template>
      </el-table-column>
      <el-table-column label="角色" align="center">
        <template #default="{ row }">
          <el-select v-model="row.roleId">
            <el-option
              v-for="item in roleList"
              :key="item.id"
              :label="item.name"
              :value="item.id"
            />
          </el-select>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="100" align="center">
        <template #default="{ $index }">
          <el-button type="danger" size="small" @click="handleDelete($index)">
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script setup lang="ts">
import { computed, nextTick, reactive, ref } from 'vue'
import useUnitStore from '@/stores/unit'
import { CascaderProps, ElMessageBox, Resolve } from 'element-plus'
import { getAllDataPermission } from '@/api/sys/dataPermission'
import useRoleStore from '@/stores/role'
import useUserStore from '@/stores/user'

const unitStore = useUnitStore()
const userStore = useUserStore()
const roleStore = useRoleStore()
const roleList = computed(() => {
  if (powerType === '1') {
    return roleStore.wxList
  } else if (powerType === '2') {
    return roleStore.manageList
  } else {
    return []
  }
})
const {
  powerType = '1',
  userId = undefined,
  permission,
} = defineProps<{
  powerType: '1' | '2'
  userId: number | undefined
  permission: string
}>()

type TableObject = {
  dataId: number
  dataIdArray: number[]
  roleId: number
}

const tableData = reactive<TableObject[]>([
  {
    dataId: undefined,
    dataIdArray: undefined,
    roleId: undefined,
  },
])

const filterList = computed<{ id: number; name: string }[]>(() => {
  const ids = userStore.getPermissionId(permission)
  if (ids) {
    return unitStore.list.filter((item) => ids.includes(item.id))
  } else {
    return []
  }
})

const cascaderOptions = computed(() => {
  if (userStore.isAdmin) {
    return unitStore.list.map((item: any) => {
      return {
        ...item,
        leaf: false,
      }
    })
  } else {
    return filterList.value.map((item: any) => {
      return {
        ...item,
        leaf: false,
      }
    })
  }
})

const cascaderProps = ref<CascaderProps>({
  value: 'id',
  label: 'name',
  leaf: 'leaf',
  lazy: true,
  lazyLoad: handleLazyLoad,
})

defineExpose({ setTableData, getTableData, checkTableData, clearTableData })

async function handleLazyLoad(node: any, resolve: Resolve) {
  if (node.data.leaf) {
    return resolve(null)
  }
  const { data } = await getAllDataPermission({
    type: powerType,
    unitId: node.data.id,
  })

  if (data.status === 200) {
    const list = data.data.map((item: any) => {
      return {
        ...item,
        leaf: true,
      }
    })
    resolve(list)
  } else {
    resolve(null)
  }
}

async function handleAdd() {
  tableData.push({
    dataId: undefined,
    dataIdArray: undefined,
    roleId: undefined,
  })
}

function handleChangeCascader(row: TableObject) {
  if (row && row.dataIdArray && row.dataIdArray.length === 2) {
    row.dataId = row.dataIdArray[1]
  } else if (row && !row.dataIdArray) {
    row.dataId = undefined
  }
}

function handleDelete(index: number) {
  ElMessageBox.confirm('确定删除此条数据吗？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  })
    .then(() => {
      tableData.splice(index, 1)
    })
    .catch(() => {})
}

async function setTableData(data: any[]) {
  tableData.length = 0
  await nextTick()
  if (data.length === 0) {
    tableData.push({
      dataId: undefined,
      dataIdArray: undefined,
      roleId: undefined,
    })
  } else {
    tableData.push(
      ...data.map((item: any) => {
        return {
          roleId: item.roleId,
          dataIdArray: item.dataIdArray?.split(',').map(Number),
          dataId: item.dataId,
        }
      }),
    )
  }
}

function getTableData() {
  return tableData.map((item: TableObject) => {
    return {
      roleId: item.roleId,
      dataIdArray: item.dataIdArray?.join(','),
      dataId: item.dataId,
      type: powerType,
      userId: userId,
    }
  })
}

function clearTableData() {
  tableData.length = 0
  tableData.push({
    dataId: undefined,
    dataIdArray: undefined,
    roleId: undefined,
  })
}

function checkTableData(rule: any, value: any, callback: any) {
  const arr = getTableData()
  if (checkHasDuplicates(arr)) {
    callback(new Error('数据权限与角色的组合存在重复,请检查！'))
    return
  } else if (!arr || arr.length === 0 || checkEmpty(arr)) {
    callback(new Error('数据权限或角色不能为空,请检查！'))
    return
  } else {
    callback()
    return
  }
}

function checkHasDuplicates(arr: any[]) {
  const seen = new Set()
  for (const obj of arr) {
    // 对属性排序，避免顺序不同导致误判
    const sortedObj = Object.keys(obj)
      .sort()
      .reduce((acc, key) => {
        acc[key] = obj[key]
        return acc
      }, {})
    const str = JSON.stringify(sortedObj)
    if (seen.has(str)) return true
    seen.add(str)
  }
  return false
}

function checkEmpty(arr: any[]) {
  return arr.some((item: any) => {
    // 不校验 userId
    delete item.userId
    return Object.values(item).some((value) => value === undefined)
  })
}
</script>

<style scoped lang="scss">
:deep(.el-select__wrapper),
:deep(.el-input__wrapper) {
  box-shadow: none;
  border-radius: unset;
}

:deep(.cell) {
  @apply pl-[1px] pr-0;
}

:deep(.el-table__body .el-table__cell) {
  @apply p-0;
}
</style>
